package Server;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import comunicationFrames.LoginRequest;
import comunicationFrames.LoginResponse;

public class LoginHandler implements Runnable {
		private Socket connection;
		private Database usersDb = new Database();
		private ObjectOutputStream socketWriter;
		private ObjectInputStream socketReader;
		private List<Socket> loginConnections;
		private Map<Long, ClientHandler> loggedUsers;
		
		public LoginHandler(List<Socket> loginConnections,
				Map<Long, ClientHandler> loggedUsers) {
			super();
			this.loginConnections = loginConnections;
			this.loggedUsers = loggedUsers;
		}

		@Override
		public void run() {
			while (true) {
				synchronized (loginConnections) {
					while (loginConnections.isEmpty()) {
						try {
							loginConnections.wait();
						} catch (InterruptedException e) {
							return;
						}
					}
					connection = (Socket) loginConnections.remove(0);
				}
				handleConnection();
			}
		}
		
		private void handleConnection() {
			try {
				socketWriter = new ObjectOutputStream(
						connection.getOutputStream());
				socketReader = new ObjectInputStream(
						connection.getInputStream());
				LoginRequest request;
				LoginResponse response;
				Object o;
				long userNumber;
				
				o = socketReader.readObject();
				if (o instanceof LoginRequest) {
					request = (LoginRequest) o;
				} else {
					response = new LoginResponse(-1, "Bad data.");
					socketWriter.writeObject(response);
					socketWriter.flush();
					close();
					return;
				}
				userNumber = loginUser(request.getUsername(),
						  		        request.getPassword());
				if (userNumber < 0) {
					response = new LoginResponse(-1,
							"Bad login or password.");
					socketWriter.writeObject(response);
					socketWriter.flush();
					close();
					return;
				}
				response = new LoginResponse(1, Long.toString(userNumber));
				socketWriter.writeObject(response);
				socketWriter.flush();
			} catch (FileNotFoundException e) {
				System.err.println(
						"Could not find requested file on the server.");
			} catch (IOException e) {
				System.err.println("Error handling a client: " + e);
			} catch (ClassNotFoundException e) {
				System.err.println("Error reading from socket: " + e);
			}
		}
		
		public void close() {
			try {
				socketWriter.close();
				socketReader.close();
			} catch (IOException e) {
				System.err.println("Error closing a server: " + e);
			}
		}
		
		private long loginUser(String username, char[] password) {
			DbContact user = usersDb.getContact(username);
			if (user == null) {
				return -1;
			}
			if (!user.getUsername().equals(username)){
				return -1;
			}
			if (!Arrays.equals(user.getPassword(), password)){
				return -1;
			}
			assert connection.isConnected()
					: "Something wrong with connection socket";
			
			ClientHandler cHandler =
					new ClientHandler(socketWriter);
			loggedUsers.put(user.getNumber(), cHandler);
			return user.getNumber();
		}
	}